package com.sc.nft.service.impl;

import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.lang.Assert;
import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.sc.nft.dao.*;
import com.sc.nft.dto.WantSellDTO;
import com.sc.nft.dto.WantSellOrderDTO;
import com.sc.nft.entity.*;
import com.sc.nft.enums.*;
import com.sc.nft.exception.GlobalRunTimeException;
import com.sc.nft.sup.ErrorCode;
import com.sc.nft.util.OrderNoUtil;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import com.sc.nft.service.ScrollWantSellService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.List;

/**
 * 卷轴商店寄售表服务接口实现
 *
 * @author zxy
 * @since 2024-09-04 02:15:00
 * @description 由 Mybatisplus Code Generator 创建
 */
@Slf4j
@RequiredArgsConstructor
@Service
public class ScrollWantSellServiceImpl implements ScrollWantSellService {
    private final ScrollWantSellDao scrollWantSellDao;
    private final EquityPropsDao equityPropsDao;
    private final UserEquityPropsDao userEquityPropsDao;
    private final StaticDataDao staticDataDao;
    private final ScrollConfigDao scrollConfigDao;
    private final SecondEquityPropsOrderDao equityPropsOrderDao;
    private final SecondEquityPropsDao secondEquityPropsDao;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void postSell(UserInfo userInfo, ScrollShop scrollShop, Long equityId, BigDecimal unitPrice, Integer count) {
        ScrollConfig config = scrollConfigDao.getConfig();
        Assert.isTrue(NumberUtil.isGreaterOrEqual(unitPrice,config.getSalesMinPrice()),()-> new GlobalRunTimeException("挂单金额不能低于"+config.getSalesMinPrice().toPlainString()+"元"));
        Assert.isTrue(NumberUtil.isLessOrEqual(unitPrice,config.getSalesMaxPrice()),()-> new GlobalRunTimeException("挂单金额不能高于"+config.getSalesMaxPrice().toPlainString()+"元"));
        Assert.isTrue(count>=config.getSalesMinCount(),()-> new GlobalRunTimeException("挂单数量不能低于"+config.getSalesMinCount()+"元"));
        Assert.isTrue(count<=config.getSalesMaxCount(),()-> new GlobalRunTimeException("挂单数量不能高于"+config.getSalesMaxCount()+"元"));
        EquityProps equityProps = equityPropsDao.getById(equityId);
        Assert.notNull(equityProps,()-> new GlobalRunTimeException("未找到对应道具"));
        Integer allreadyCount = scrollWantSellDao.getCountByShopId(scrollShop.getId());
        Assert.isTrue(allreadyCount<config.getSalesOrderMaxCount(),()->new GlobalRunTimeException(ErrorCode.WANT_SELL_LIMIT));
        Integer havingCountByUserId = userEquityPropsDao.getHavingCountByUserId(equityId, userInfo.getId());
        Assert.isTrue(havingCountByUserId-config.getSalesFreezeCount()>=count,()-> new GlobalRunTimeException("道具数量不足"));
        int updateSuccessCount = userEquityPropsDao.updateHavingToShopSell(equityId, userInfo.getId(), count);
        Assert.isTrue(count.intValue()==updateSuccessCount,()-> new GlobalRunTimeException(ErrorCode.FAIL_TO_EDIT));
        ScrollWantSell scrollWantSell = new ScrollWantSell();
        scrollWantSell.setStatus(WantSellOrderStatusEnum.IN_BUY);
        scrollWantSell.setWantSellCount(count);
        scrollWantSell.setSumPrice(unitPrice.multiply(BigDecimal.valueOf(count)));
        scrollWantSell.setSalesCount(0);
        scrollWantSell.setFreezeCount(0);
        scrollWantSell.setBackCount(0);
        scrollWantSell.setSalesFeeAmount(BigDecimal.ZERO);
        scrollWantSell.setShopId(scrollShop.getId());
        scrollWantSell.setShopUserId(userInfo.getId());
        scrollWantSell.setUnitPrice(unitPrice);
        scrollWantSell.setSalesPrice(BigDecimal.ZERO);
        scrollWantSell.insert();


    }

    @Override
    public Page<ScrollWantSell> myWantSellPage(UserInfo user, Page mp) {
        return scrollWantSellDao.myWantSellPage(user.getId(),mp);
    }

    @Override
    public Page<WantSellDTO> wantSellPage(Long shopId, Page mp) {
        return scrollWantSellDao.wantSellPage(shopId,mp);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void closeWantSellOrder(Long id, UserInfo user, String dealPassword) {
        ScrollWantSell wantSell = scrollWantSellDao.getById(id);
        Assert.notNull(wantSell,()-> new GlobalRunTimeException("未找到出售单"));
        Assert.isTrue(wantSell.getShopUserId().longValue()==user.getId().longValue(),()-> new GlobalRunTimeException(ErrorCode.ORDER_NOT_FOUND));
        Assert.isTrue(wantSell.getStatus()==WantSellOrderStatusEnum.IN_BUY,()->new GlobalRunTimeException(ErrorCode.ORDER_STATUS_ERROR));
        Assert.isTrue(wantSell.getFreezeCount()<=0,()->new GlobalRunTimeException("存在被冻结的订单，请稍后再试"));
        if(!StrUtil.equals(user.getTransactionPassword(),dealPassword)){
            throw new GlobalRunTimeException(ErrorCode.PAYMENT_PASSWORD_WAS_ENTERED_INCORRECTLY);
        }
        wantSell.setStatus(WantSellOrderStatusEnum.CLOSE);
        wantSell.setBackCount(wantSell.getWantSellCount()-wantSell.getSalesCount());
        wantSell.updateById();

        StaticData scrollPropsId = staticDataDao.getByType("scroll_props_id");
        Long equityId = Long.parseLong(scrollPropsId.getValue());
        Integer backCount = userEquityPropsDao.updateShopSellToHaving(equityId, user.getId(), wantSell.getBackCount());
        Assert.isTrue(wantSell.getBackCount().intValue()==backCount.intValue(),()->new GlobalRunTimeException(ErrorCode.FAIL_TO_EDIT));
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public WantSellOrderDTO userBuyShopOrder(Long id, UserInfo user, Integer count) {
        ScrollWantSell wantSell = scrollWantSellDao.getById(id);
        Assert.notNull(wantSell,()-> new GlobalRunTimeException("未找到出售单"));
        Assert.isTrue(wantSell.getStatus()==WantSellOrderStatusEnum.IN_BUY,()->new GlobalRunTimeException(ErrorCode.ORDER_STATUS_ERROR));
        Assert.isFalse(equityPropsOrderDao.hasWaitPayOrder(user.getId()), () -> new GlobalRunTimeException(ErrorCode.WAIT_PAY_ORDER));
        Assert.isFalse(wantSell.getShopUserId().longValue()==user.getId(),()-> new GlobalRunTimeException("无法购买自己的店铺的商品"));
        StaticData scrollPropsId = staticDataDao.getByType("scroll_props_id");
        Long equityId = Long.parseLong(scrollPropsId.getValue());
        Assert.isTrue(wantSell.getWantSellCount()-wantSell.getFreezeCount()-wantSell.getSalesCount()>=count,()-> new GlobalRunTimeException("店铺销售数量不足"));
        List<UserEquityProps> shopEquityProps = userEquityPropsDao.getOnSellListByUserIdAndEquityPropsIdAndLimit(equityId,wantSell.getShopUserId(),  count);
        if(shopEquityProps.size()<count){
            throw new GlobalRunTimeException("店铺销售数量不足");
        }
        ScrollConfig config = scrollConfigDao.getConfig();
        BigDecimal fee = NumberUtil.max(wantSell.getUnitPrice().multiply(config.getSalesFeeRatio()).setScale(2, BigDecimal.ROUND_HALF_UP),config.getSalesMinFeeAmount());
        DateTime now = DateTime.now();
        BigDecimal sumPrice = BigDecimal.ZERO;
        DateTime closeTime = DateUtil.offsetMinute(now, 3);
        List<Long> orderIds = new ArrayList<>();
        for (UserEquityProps shopEquityProp : shopEquityProps) {
            shopEquityProp.setOnConsign(UserEquityConsignStatusEnum.CONSIGN_FREEZE);
            shopEquityProp.updateById();
            SecondEquityPropsOrder order = new SecondEquityPropsOrder();
            order.setSecondEquityPropsId(0L);
            order.setEquityPropsId(equityId);
            order.setUserEquityPropsId(shopEquityProp.getId());
            order.setSalesUserId(wantSell.getShopUserId());
            order.setBuyUserId(user.getId());
            order.setBuyPrice(wantSell.getUnitPrice());
            order.setCharge(fee);
            order.setStatus(OrderStatusEnum.WAIT_PAY);
            order.setOrderNo(OrderNoUtil.getOrderNo(String.valueOf(PayTypeEnum.SECOND_EQUITY_PROPS.getCode())));
            order.setDealTime(now);
            order.setCloseTime(closeTime);
            order.setPayTime(order.getDealTime());
            order.setRealAmount(order.getBuyPrice().subtract(order.getCharge()));
            Assert.isTrue(NumberUtil.isGreater(order.getRealAmount(),BigDecimal.ZERO),()->new GlobalRunTimeException("手续费超出了实际付款金额"));
            order.setFirstTitle(shopEquityProp.getFirstTitle());
            order.setBuySumCount(1);
            order.setIsSettlePay(false);
            order.setWantSellOrderId(wantSell.getId());
            order.setShopId(wantSell.getShopId());
            order.insert();
            sumPrice = sumPrice.add(order.getBuyPrice());
            orderIds.add(order.getId());
        }
        scrollWantSellDao.addFreeze(wantSell.getId(),count);
        WantSellOrderDTO wantSellOrderDTO = new WantSellOrderDTO();
        wantSellOrderDTO.setEquityId(equityId);
        wantSellOrderDTO.setCount(count);
        wantSellOrderDTO.setExpirationTimeStamp(closeTime.getTime());
        wantSellOrderDTO.setNowTimeStamp(now.getTime());
        wantSellOrderDTO.setUnitPrice(wantSell.getUnitPrice().toPlainString());
        wantSellOrderDTO.setSumPrice(sumPrice.toPlainString());
        wantSellOrderDTO.setOrderIds(orderIds);
        return wantSellOrderDTO;
    }
}